/**
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-26 18:32:44
 * @Description  : 科目接口验证中间件
 */

const Joi = require('joi')
const { Op } = require('sequelize')
const R = require('@/models/Response')
const { Exam } = require('@/models/model')
const { ERROR_SYSTEM_CODE, ERROR_USER_CODE } = require('@/constants/errorCode')
const { IS_INTEGER, IS_UNSAFE_INTEGER } = require('@/constants/joiSchema')
const { dumpCheck: globalDumpCheck } = require('@/utils/dumpCheck')

const examSchema = {
  examIds: Joi.array().items(IS_UNSAFE_INTEGER),
  examId: IS_UNSAFE_INTEGER,
  page: IS_INTEGER.min(1).default(1),
  pageSize: IS_INTEGER.min(1).default(999),
  name: Joi.string().min(1).max(255),
  pid: IS_UNSAFE_INTEGER,
  pic: Joi.string().allow(''),
  price: Joi.number().min(0).max(1000)
}

const dumpCheck = {
  /**
   * @author: Hejh(3010733382@qq.com)
   * @description: 验证科目ID的合法性
   * @param {array<string>} examIds 科目ID数组
   * @param {boolean} isLink 需要为外链
   * @param {boolean} isExamTo 需要为内部科目
   */
  checkExamIds: async (examIds) => {
    let newexamIds = [...new Set(examIds)]
    // 不能出现重复的
    if (newexamIds.length !== examIds.length) {
      return false
    }

    newexamIds = newexamIds.map((item) => BigInt(item))

    if (newexamIds.length === 0) {
      return true
    }

    // 查看不重复的和数据库的是否对的上
    const myWhere = {
      id: {
        [Op.in]: newexamIds
      }
    }
    const exams = await Exam.findAll({
      where: myWhere
    })
    if (exams.length !== newexamIds.length) {
      return false
    }

    return true
  }
}

/**
 * @description 科目列表查询的参数验证
 * @param {*} ctx
 * @param {*} next
 * @returns
 */
module.exports.listExamValidate = async (ctx, next) => {
  const schema = Joi.object({
    page: examSchema.page,
    pageSize: examSchema.pageSize,
    pid: examSchema.pid
  }).validate(ctx.query)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }
  ctx.newQuery = schema.value
  await next()
}

/**
 * @description 创建科目时的参数验证
 * @param {*} ctx
 * @param {*} next
 * @returns
 */
module.exports.createExamValidate = async (ctx, next) => {
  const schema = Joi.object({
    name: examSchema.name.required(),
    pid: examSchema.pid.required(),
    pic: examSchema.pic,
    price: examSchema.price
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { pid } = ctx.request.body

  const b4 = await globalDumpCheck.checkExamIds([pid], true)
  // TODO 验证pid的合法性
  if (!b4) {
    ctx.body = R.error(ERROR_USER_CODE.EXAM_ID_ERROR)
    return
  }

  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 更新科目时的参数验证
 * @param {*} ctx
 * @param {*} next
 */
module.exports.updateExamValidate = async (ctx, next) => {
  const schema = Joi.object({
    examId: examSchema.examId.required(),
    name: examSchema.name.required(),
    pid: examSchema.pid.required(),
    price: examSchema.price,
    pic: examSchema.pic
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  //TODO 验证 pid 和 examId的合法性
  const { examId, pid } = ctx.request.body
  const b4 = await globalDumpCheck.checkExamIds([examId])
  const b5 = await globalDumpCheck.checkExamIds([pid], true)
  if (!b4 || !b5) {
    ctx.body = R.error(ERROR_USER_CODE.EXAM_ID_ERROR)
    return
  }

  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量删除科目接口的参数验证
 * @param {*} ctx
 * @param {*} next
 */
module.exports.delExamsValidate = async (ctx, next) => {
  const schema = Joi.object({
    examIds: examSchema.examIds.required()
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { examIds } = ctx.request.body

  // 验证科目ID数组的合法性
  const b4 = await dumpCheck.checkExamIds(examIds)
  if (!b4) {
    ctx.body = R.error(ERROR_USER_CODE.EXAM_ID_ERROR)
    return
  }
  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量删除科目接口的参数验证
 * @param {*} ctx
 * @param {*} next
 */
module.exports.getExamByIdValidate = async (ctx, next) => {
  const schema = Joi.object({
    examId: examSchema.examIds.required()
  }).validate(ctx.query)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { examId } = ctx.query

  // 验证科目ID数组的合法性
  const b4 = await dumpCheck.checkExamIds([examId])
  if (!b4) {
    ctx.body = R.error(ERROR_USER_CODE.EXAM_ID_ERROR)
    return
  }
  await next()
}
